package pdm.traj.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import pdm.traj.util.timeslot.DateFileOffsetTSMap;
import pdm.traj.util.timeslot.FileTimeSlotMap;
import pdm.traj.util.timeslot.TimeSlot;


public class PathUtil {
	private static SimpleDateFormat DATE_FORMAT = TrajConstants.DATE_FORMAT;
	private static SimpleDateFormat TIMESTAMP_FORMAT = TrajConstants.TIMESTAMP_FORMAT;
	
	public final static List<FileTimeSlotMap> linkedDataMap;
	public final static List<FileTimeSlotMap> builtDataMap;
	private List<FileTimeSlotMap> map = linkedDataMap;
	private int step = 15;
	static {
		int i, j;
		//initiate linked data map
		linkedDataMap = new ArrayList<FileTimeSlotMap>();
		Iterator<TimeSlot> it = TimeSlot.getLinkedDataTimeSlotList().iterator();
		for (i = 0; i < 24; i++) {
			FileTimeSlotMap ftsm = new FileTimeSlotMap(String.format("%02d", i), 0, it.next());
			linkedDataMap.add(ftsm);
		}
		
		//initiate built data map
		builtDataMap = new ArrayList<FileTimeSlotMap>();
		it = TimeSlot.getBuiltDataTimeSlotList().iterator();
		for (i = 0; i < 24; i++) {
			for (j = 0; j < 4; j++) {
				FileTimeSlotMap ftsm = new FileTimeSlotMap(String.format("%02d", i), j, it.next());
				builtDataMap.add(ftsm);
			}
		}
	}
	
	/**
	 * to next timestamp
	 * @param d
	 * @param step
	 */
	public static void toNextTimeStamp(Date d, int step) {
		d.setTime(d.getTime() + TrajConstants.ONE_MINUTE_IN_MILLISEC * step);
	}
	
	/**
	 * get part data paths
	 * @param startTime
	 * @param endTime
	 * @return
	 */
	public List<String> getPartDataPathsByDuration(String startTime, String endTime) {
		Date st, et, d;
		FileTimeSlotMap ftsm;
		String str;
		List<String> result = null;
		try {
			st = TIMESTAMP_FORMAT.parse(startTime);
			et = TIMESTAMP_FORMAT.parse(endTime);
			d = (Date) st.clone();
			result = new ArrayList<String>(); 
			while (d.before(et)) {
				ftsm = getMapForTime(d);
				str = DATE_FORMAT.format(d) + "/" + ftsm.getFilePath();
				if (!result.contains(str)) {
					result.add(str);
				}
				toNextTimeStamp(d, step);
			}
			ftsm = getMapForTime(et);
			str = DATE_FORMAT.format(et) + "/" + ftsm.getFilePath();
			if (!result.contains(str)) {
				result.add(str);
			}
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return result;
	}
	
	/**
	 * get part data paths
	 * @param startTime
	 * @param endTime
	 * @return
	 */
	public List<String> getKeyPostfixByDuration(String startTime, String endTime) {
		Date st, et, d;
		FileTimeSlotMap ftsm;
		String str;
		List<String> result = null;
		try {
			st = TIMESTAMP_FORMAT.parse(startTime);
			et = TIMESTAMP_FORMAT.parse(endTime);
			d = (Date) st.clone();
			result = new ArrayList<String>(); 
			while (d.before(et)) {
				ftsm = getMapForTime(d);
				str = DATE_FORMAT.format(d) + "_" + ftsm.getFilePath();
				if (!result.contains(str)) {
					result.add(str);
				}
				toNextTimeStamp(d, step);
			}
			ftsm = getMapForTime(et);
			str = DATE_FORMAT.format(et) + "_" + ftsm.getFilePath();
			if (!result.contains(str)) {
				result.add(str);
			}
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return result;
	}
	
	/**
	 * get part data paths for buildTraj
	 * @param startTime
	 * @param endTime
	 * @return
	 */
	public List<String> getPartDataPathsByDurationForBuildTraj(String startTime, String endTime) {
		Date st, et, d;
		FileTimeSlotMap ftsm;
		String str;
		List<String> result = null;
		try {
			st = TIMESTAMP_FORMAT.parse(startTime);
			et = TIMESTAMP_FORMAT.parse(endTime);
			toNextTimeStamp(st, -60);
			toNextTimeStamp(et, 60);
			d = (Date) st.clone();
			result = new ArrayList<String>(); 
			while (d.before(et)) {
				ftsm = getMapForTime(d);
				str = DATE_FORMAT.format(d) + "/" + ftsm.getFilePath();
				if (!result.contains(str)) {
					result.add(str);
				}
				toNextTimeStamp(d, step);
			}
			ftsm = getMapForTime(et);
			str = DATE_FORMAT.format(et) + "/" + ftsm.getFilePath();
			if (!result.contains(str)) {
				result.add(str);
			}
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * get part data maps 
	 * @param startTime
	 * @param endTime
	 * @return
	 */
	public List<DateFileOffsetTSMap> getPartDataPathMapsByDuration(String startTime, String endTime) {
		Date st, et, d;
		FileTimeSlotMap ftsm;
		List<DateFileOffsetTSMap> result = null;
		DateFileOffsetTSMap map;
		try {
			st = TIMESTAMP_FORMAT.parse(startTime);
			et = TIMESTAMP_FORMAT.parse(endTime);
			d = (Date) st.clone();
			result = new ArrayList<DateFileOffsetTSMap>(); 
			while (d.before(et)) {
				ftsm = getMapForTime(d);
				map = new DateFileOffsetTSMap(DATE_FORMAT.format(d), ftsm);
				if (!DateFileOffsetTSMap.contains(result, map)) {
					result.add(map);
				}
				toNextTimeStamp(d, step);
			}
			ftsm = getMapForTime(et);
			map = new DateFileOffsetTSMap(DATE_FORMAT.format(et), ftsm);
			if (!DateFileOffsetTSMap.contains(result, map)) {
				result.add(map);
			}
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return result;
	}

	
	//******* test start
	private static void testGetPartDataPathsByDuration() {
		System.out.println("strs:");
		PathUtil pu = new PathUtil();
		List<String> l;
		System.out.println("linked:");
		pu.setMap(PathUtil.linkedDataMap);
		l = pu.getPartDataPathsByDuration("2010-09-25 02:23:32", "2010-09-26 04:33:32");
		for (String s : l) {
			System.out.println(s);
		}
		System.out.println("built:");
		pu.setMap(PathUtil.builtDataMap);
		l = pu.getPartDataPathsByDuration("2010-09-25 02:23:32", "2010-09-26 04:33:32");
		for (String s : l) {
			System.out.println(s);
		}
	}
	
	private static void testGetPartDataPathMapsByDuration() {
		System.out.println("maps:");
		PathUtil pu = new PathUtil();
		List<DateFileOffsetTSMap> l;
		System.out.println("linked:");
		pu.setMap(linkedDataMap);
		l = pu.getPartDataPathMapsByDuration("2010-09-25 02:23:32", "2010-09-26 04:33:32");
		for (DateFileOffsetTSMap s : l) {
			System.out.println(s);
		}
		System.out.println("built:");
		pu.setMap(builtDataMap);
		l = pu.getPartDataPathMapsByDuration("2010-09-25 02:23:32", "2010-09-26 04:33:32");
		for (DateFileOffsetTSMap s : l) {
			System.out.println(s);
		}
	}
	
	private static void printLinkedDataMap() {
		System.out.println("linked: ");
		for (FileTimeSlotMap ftsm : linkedDataMap) {
			System.out.println(ftsm);
		}
	}
	
	private static void printBuiltDataMap() {
		System.out.println("built: ");
		for (FileTimeSlotMap ftsm: builtDataMap) {
			System.out.println(ftsm);
		}
	}
	
	private static void test() {
//		testGetPartDataPathsByDuration();
//		testGetPartDataPathMapsByDuration();
		printLinkedDataMap();
		printBuiltDataMap();
	}
	
	public static void test2() {
		PathUtil pu = new PathUtil();
		List<String> l;
		System.out.println("linked:");
		pu.setMap(PathUtil.linkedDataMap);
		l = pu.getPartDataPathsByDuration("2010-09-25 02:23:32", "2010-09-26 04:33:32");
		for (String s : l) {
			System.out.println(s);
		}
	}
	
	//******* test end
	public FileTimeSlotMap getMapForTime(Date d) {
		Iterator<FileTimeSlotMap> it = map.iterator();
		FileTimeSlotMap ftsm;
		while (it.hasNext()) {
			ftsm = it.next();
			if (ftsm.inSlot(d)) {
				return ftsm;
			}
		}
		return null;
	}
	
	public List<FileTimeSlotMap> getMap() {
		return map;
	}

	public void setMap(List<FileTimeSlotMap> map) {
		this.map = map;
	}
	
	public int getStep() {
		return step;
	}

	public void setStep(int step) {
		this.step = step;
	}

	public static void main(String[] args) {
//		test();
		test2();
	}
}
